#include "Headers/filethread.h"

FileThread::FileThread()
{
    server_downloadPath= QCoreApplication::applicationDirPath() + "/../server";
    QDir dir;
    if(!dir.exists(server_downloadPath)) {
        dir.mkdir(server_downloadPath);
    }
}

void FileThread::FileTcp(){
    FileTcpPort=1113;
    FileTcpServer = new QTcpServer();
    FileTcpServer->listen(QHostAddress::Any,FileTcpPort);
    connect(FileTcpServer, &QTcpServer::newConnection, this,[=](){
        QTcpSocket* socketr = FileTcpServer->nextPendingConnection();
        // 使用 QPointer 来管理 socket 的生命周期
        QPointer<QTcpSocket> socket(socketr);
        connect(socket, &QTcpSocket::readyRead, [=]() {
            if(is_dow[socket]){
                fileDataRead(socket);
                return;
            }
            QString data = socket->readAll();
            QJsonDocument jsonDocument = QJsonDocument::fromJson(data.toUtf8());
            QVariant variant = jsonDocument.toVariant();
            QMap<QString, QVariant> map = variant.toMap();
            QString User = map["User"].toString();
            QString Sender = map["Sender"].toString();
            int Type = map["Type"].toInt();
            if(Type==JOIN_TYPE){
                UserList[socket]=User;
                FileTcpList[User]=socket;
            }else if(Type==FILE_INFO_TYPE){
                fileSendUser[FileTcpList[Sender]]=FileTcpList[User];
                fileToUser[FileTcpList[User]]=FileTcpList[Sender];
                fileSendUserList[socket]=Sender;
                is_dow[socket]=true;
                clientData[socket]=data;
                fileInfoRead(map);
            }else if(Type==FILE_OK_TYPE){
                ToServerFileData(fileToUser[socket]);
            }else if(FileTcpList[User]!=nullptr){
                FileTcpList[User]->write(data.toUtf8());
                QThread::msleep(10); //添加延时
                qDebug()<< "传输文件信息，大小："<< m_sendFileSize;
                //等待发送完成，才能继续下次发送，否则发送过快，对方无法接收
                if(!FileTcpList[User]->waitForBytesWritten(10*1000)) {
                    qDebug()<<(QString("网络请求超时,原因：%1").arg(FileTcpList[User]->errorString()));
                    return;
                }
            }else if(Type==FILE_RECEIVE_OK_TYPE){
                fileToUser[socket]->write(data.toUtf8());
            }else{
                //SQL存储，等待用户上线再发送
                return ;
            }
        });
    });
}

/*接收文件*/
void FileThread::fileInfoRead(QMap<QString, QVariant> map)
{
    qDebug()<<"文件信息读取on_fileInfoRead......";
    // 接收文件大小，数据总大小信息和文件名大小,文件名信息
    QString Sender = map["Sender"].toString();
    ServerFileInfo[Sender] = new MyFileInfo();
    ServerFileInfo[Sender]->fileName = map["FileName"].toString();
    ServerFileInfo[Sender]->fileSize = map["FileSize"].toInt();
    auto socket = FileTcpList[Sender];
    // 获取文件名，建立文件
    qDebug()<<(QString("Client下载文件 %1, 文件大小：%2").arg(ServerFileInfo[Sender]->fileName).arg(ServerFileInfo[Sender]->fileSize));
    filePath[Sender] = server_downloadPath + "/" + ServerFileInfo[Sender]->fileName;
    m_localFile[socket]=filePath[Sender];
    m_sendFileSize[socket]=ServerFileInfo[Sender]->fileSize;
    ServerFileInfo[Sender]->localFile.setFileName(filePath[Sender]);
    if(ServerFileInfo[Sender]->fileSize>1024*1024) {
        getServerFileSize[Sender] = QString("%1M").arg(ServerFileInfo[Sender]->fileSize/1024/1024.0);
    }
    else {
        getServerFileSize[Sender] = QString("%1KB").arg(ServerFileInfo[Sender]->fileSize/1024.0);
    }

    // 打开文件，准备写入
    if(!ServerFileInfo[Sender]->localFile.open(QIODevice::WriteOnly)) {
        qDebug()<<"文件打开失败！"<< ServerFileInfo[Sender]->localFile.errorString();  ;
    }
    //文件信息获取完成，接着获取文件数据
    QByteArray senddata=(QString(R"({
                             "Type":%1
                             })").arg(FILE_OK_TYPE)).toUtf8();
    qDebug()<<FileTcpList[Sender];
    FileTcpList[Sender]->write(senddata);
    QThread::msleep(10); //添加延时
    qDebug()<< "传输文件信息，大小："<< m_sendFileSize;
    //等待发送完成，才能继续下次发送，否则发送过快，对方无法接收
    if(!FileTcpList[Sender]->waitForBytesWritten(10*1000)) {
        qDebug()<<(QString("网络请求超时,原因：%1").arg(FileTcpList[Sender]->errorString()));
        return;
    }
}
void FileThread::fileDataRead(QTcpSocket* socket)
{
    qint64 readBytes = socket->bytesAvailable();
    if(readBytes <0) return;
    int progress = 0;
    QString Sender = fileSendUserList[socket];
    // 如果接收的数据大小小于要接收的文件大小，那么继续写入文件
    if(ServerFileInfo[Sender]->bytesReceived < ServerFileInfo[Sender]->fileSize) {
        // 返回等待读取的传入字节数
        QByteArray data = socket->read(readBytes);
        qint64 size = data.size();
        ServerFileInfo[Sender]->bytesReceived+=size;
        qDebug()<<(QString("接收进度：%1/%2(字节)").arg(ServerFileInfo[Sender]->bytesReceived).arg(ServerFileInfo[Sender]->fileSize));
        progress =static_cast<int>(ServerFileInfo[Sender]->bytesReceived*100/ServerFileInfo[Sender]->fileSize);
        ServerFileInfo[Sender]->progressByte = ServerFileInfo[Sender]->bytesReceived;
        ServerFileInfo[Sender]->progressStr = QString("%1").arg(progress);
        ServerFileInfo[Sender]->localFile.write(data);
    }

    // 接收数据完成时
    if (ServerFileInfo[Sender]->bytesReceived>=ServerFileInfo[Sender]->fileSize){
        qDebug()<<(tr("接收文件[%1]成功！").arg(ServerFileInfo[Sender]->fileName));
        progress = 100;
        ServerFileInfo[Sender]->localFile.close();
        qDebug()<<(QString("接收进度：%1/%2（字节）").arg(ServerFileInfo[Sender]->bytesReceived).arg(ServerFileInfo[Sender]->fileSize));
        ServerFileInfo[Sender]->progressByte = ServerFileInfo[Sender]->bytesReceived;
        ServerFileInfo[Sender]->initReadData();
        is_dow[socket]=false;
        fileSendUser[socket]->write(clientData[socket].toUtf8());
        QThread::msleep(10); //添加延时
        qDebug()<< "传输文件信息，大小："<< m_sendFileSize;
        //等待发送完成，才能继续下次发送，否则发送过快，对方无法接收
        if(!fileSendUser[socket]->waitForBytesWritten(10*1000)) {
            qDebug()<<(QString("网络请求超时,原因：%1").arg(fileSendUser[socket]->errorString()));
            return;
        }
    }
}

void FileThread::ToServerFileData(QTcpSocket *socket)
{

    qint64 payloadSize = 1024*10; //每一帧发送1024*64个字节，控制每次读取文件的大小，从而传输速度
    double progressByte= 0;//发送进度
    qint64 bytesWritten=0;//已经发送的字节数
    QFile file(m_localFile[socket]);
    file.open((QIODevice::ReadOnly));
    while(bytesWritten != m_sendFileSize[socket]) {
        int  progress = static_cast<int>(bytesWritten/1.0/m_sendFileSize[socket]*100);
        if(bytesWritten<m_sendFileSize[socket]){
            QByteArray DataInfoBlock = file.read(qMin(m_sendFileSize[socket],payloadSize));
            qint64 WriteBolockSize = fileSendUser[socket]->write(DataInfoBlock, DataInfoBlock.size());
            QThread::usleep(3); //添加延时，防止服务端发送文件帧过快，否则发送过快，客户端接收不过来，导致丢包
            //等待发送完成，才能继续下次发送，
            if(!fileSendUser[socket]->waitForBytesWritten(3*1000)) {
                qDebug()<<("网络请求超时");
                return;
            }
            bytesWritten += WriteBolockSize;
        }


        if(bytesWritten>=m_sendFileSize[socket]){
            //LogWrite::LOG_DEBUG(QString("当前更新进度：100%,发送总次数:%1").arg(count), "server_"+socket->localAddress().toString());
            qDebug()<<(QString("当前上传进度：%1/%2 -> %3%").arg(bytesWritten).arg(m_sendFileSize[socket]).arg(progress));
            qDebug()<<(QString("-------------对[%1]的文件传输完成！------------------").arg(socket->peerAddress().toString()));
            file.close();
            return;
        }

        if(bytesWritten/1.0/m_sendFileSize[socket] > progressByte) {
            qDebug()<<(QString("当前上传进度：%1/%2 -> %3%").arg(bytesWritten).arg(m_sendFileSize[socket]).arg(progress));
            progressByte+=0.1;
        }
    }
}

void FileThread::run(){
    FileTcp();
    exec();
}
